/**
 * class name: tab$,
 * copyright: maximus zhang,
 * License: MIT-LICENSE,
 * contact: maximus.zhang@gmail.com,
 * required-js: http://hcjs.googlecode.com/svn/trunk/hc.js,
 * update: http://hcjs.googlecode.com/svn/trunk/tab.js
 * -------
 * todo: remove tab; key$; tab moving; tab pull out as popup; popup to tab
 */
function tab$(){/* {id,elem,css,{tabs}} */
    var A = arguments,
        _=this;
    _ = ext$( _, ext$( {
        id : 'tab'+ now$(3),
        elem : me.body,
        css : '',
        ttl : 600,
        ico : {'close': '/icos/ishut.gif'},
        tabs : [
            {
                id:'newtab1',
                tab : { label:'', cls:'', css:'' },
                ico : {src:'', css:'', alt:''},
                fn : function(){},
                key : '',
                data : '',
                locked : false,
                ttl : null
            }
        ] }, A[0]) );

    _.uitype = 'tab$';

    _.elem = $(_.elem) || me.body;

    _.$ = {};/* store tab's data element */
    _.tab$ = {};/* store tabs json data */
    _.times = {};

    _.active = null;
    _.num = 0;

    _.timer$ = function(a){
        if ( !a || !a.nodeName=='A' ) {
            return false;
        }

        var id = attr$(a,'href').replace(/^#/,'');

        if ( id=='' ) {
            return false;
        }

        if ( hop(_.times, id) ) {
            var ttl = typeof _.tab$[id].ttl=='number'
                ? _.tab$[id].ttl
                : _.ttl;

            if ( parseInt((now$(2)-_.times[id])/1000, 10)>= ttl ) {
                delete _.times[id];
                return true;
            }
        }

    return false;
    };

    _.go$ = function(a){
        if ( typeof a=='string' ) {
            if ( !hop(_.tab$, a) ) {
                return false;
            }

            var a = $(_.tab$[a].id);
        } else if ( typeof a == 'object' ) {
            var a = $(a.id);
        }

        if ( a.nodeName && a.nodeName!='A' ) {
            a=a.firstChild;
        }

        _.click$.apply(a);

    return _;
    };

    _.click$ = function(){/* to be call or apply only!! */
        if ( _.active && _.active.nodeName ) {
            if ( _.active==this ) {
                return true;
            }

            _.active.className = '';
            _.times[attr$(_.active,'href').replace(/^#/,'')] = now$(2);
        }

        this.className = 'a';

        var id = attr$(this,'href').replace(/^#/,'');

        if ( typeof _.tab$[id].data=='function' ) {
            if ( _.timer$(this) ) {
                _.tab$[id].data(this);
            }
        }

        _.togg$.apply(this, [id]);
        _.active = this;

    return _;
    };

    _.togg$ = function(a){/* to be call or apply only!! */
        if ( !a || a=='' || !_.$[a] ) {
            return null;
        }

        if ( _.active && _.active.nodeName ) {
            if ( _.active==this ) {
                return false;
            }
        }

        var pd = attr$(_.active,'href').replace(/^#/,'');

        if ( _.$[pd] && _.$[pd].nodeName ) {
            _.$[pd].className='x';
        } else {
            for ( var v in _.$ ) {
                _.$[v].className = 'x';
            }
        }

        _.$[a].className = 'v';

    return true;
    };

    _.add$ = function(ot, el){
        if ( !ot || !el ) {
            return false;
        }

        if ( hop(_.$, ot.id) ) {
            return _.go$(ot.id);
        }

        var li = el$('li').appendTo$(el);

        li.id = p$(ot, 'id') && !$(ot.id) ? ot.id : '_tab_'+ now$(2)*Math.random();
        if ( !p$(ot, 'id') || ot.id!=li.id ) {
            ot.id = li.id;
        }

        var a = el$('a').appendTo$(li);
        a.href = '#'+  li.id;
        if ( p$(ot,'tab','cls') ) {
            a.className = ot.tab.cls;
            if ( ot.tab.cls=='a' ) {
                if ( _.active && _.active.nodeName ) {
                    _.active.className = '';

                    var pd = attr$(_.active, 'href').replace(/^#/, '');

                    _.times[pd] = now$(2);
                }

                if ( _.$[pd] && _.$[pd].nodeName ) {
                    _.$[pd].className = 'x';
                } else {
                    for ( var v in _.$ ) {
                        _.$[v].className = 'x';
                    }
                }
                _.active = a;
            }
        }

        if ( p$(ot, 'tab', 'css') ) {
            a.style.cssText = ot.tab.css;
        }

        a.onclick = function(ev){
            if ( _.click$.apply(this, [ot.data]) ) {
                return false;
            }

            if ( typeof ot.fn=='function' ) {
                ot.fn.apply(this, [ot.data]);
            }

        return false;
        };

        if ( p$(ot, 'ico', 'src') ) {
            var ico = el$('img').appendTo$(a);
            ico.src = ot.ico.src;
            ico.className = 'ico';
            ico.alt = ot.ico.alt || '';
        }

        if ( p$(ot.tab,'label') ) {
            var tx = el$('span').appendTo$(a);
            tx.id = li.id +'_label';
            tx.className = 't';
            tx.innerHTML = ot.tab.label;
        }

        if ( p$(ot,'key') ) {
            var em = el$('em').appendTo$(a);
            em.innerHTML = '(<kbd>'+ ot.key +'<\/kbd>)';
        }

        var dv = el$('div').appendTo$(_.tabdata),
            pz = pos$(_.elem);

        dv.className = _.active==a ? 'v':'x';
        dv.id = li.id +'_tab';

        var div = el$('div').appendTo$(dv);

        if ( typeof ot.data=='function' ) {
            var dat = ot.data.apply(div,[a]);
            if ( typeof dat=='string' ) {
                div.innerHTML = dat;
            }
        } else if ( typeof ot.data=='string' ) {
            div.innerHTML = ot.data;
        } else if ( typeof ot.data=='object' && ot.data.nodeType ) {
            div.appendChild(ot.data);
        }

        /* tab close */
        if ( !ot.locked ) {
            var xx = el$('span').appendTo$(a);

            xx.className = 'xx';
            xx.title = 'close tab';
            xx.style.cssText = 'background:url('+ _.ico.close +') 0 0 no-repeat;';

            xx.onmouseover = function(){
                this.style.backgroundPosition = '-16px 0';
            };

            xx.onmouseout = function(){
                this.style.backgroundPosition='0 0';
            };

            xx.onclick=function(){
                if ( _.num<2 ) {
                    return false;
                }

                a.onclick = function(){return false;};

                try {
                    delete _.$[li.id];
                    delete _.tab$[li.id];
                    _.tabroot.removeChild(li);
                    div.empty$();
                    dv.empty$();
                    _.tabdata.removeChild(dv);
                } catch (ex) {
                }

                if ( _.active==a ) {
                    _.active = null;
                    for (var t in _.tab$) {
                        if ( _.active ) {
                            break;
                        }
                        if ( $(_.tab$[t].id).firstChild.nodeName=='A' ) {
                            $(_.tab$[t].id).firstChild.className = 'a';

                            if ( hop(_.$, _.tab$[t].id) ) {
                                _.$[_.tab$[t].id].className = 'v';
                            }

                            _.active = $(_.tab$[t].id).firstChild;
                        }
                    }
                }

                _.num--;

            return false;
            };
        }

        _.tab$[li.id] = ot;
        _.$[li.id] = dv;

        _.num++;

    return li;
    };

    _.new$ = function(ot){
        if ( hop(_.tab$, ot.id) ) {
            _.go$(ot);
        return _;
        }

        void _.add$(ot, _.tabroot);

    return _;
    };

    _.init$ = function(){
        var pz = pos$(_.elem);
        if ( _.elem.parentNode==me.body ) {
            _.elem.style.top = pz.top+25 +'px';
            if ( $$.msie && $$.version<7 ) {
                me.documentElement.style.paddingTop = _.elem.style.top;
            }
        }
        _.root = el$('div').before$(_.elem).class$('tab');
        _.root.style.cssText = 'height:25px;top:'+ pz.top +'px';

        _.id = _.root.id = p$(_,'id') && !$(_.id) ? _.id : ('tab'+ now$(3));

        pz = pos$(_.root);

        _.tabdata = el$('div').class$('tab').appendTo$(_.elem);

        var bar = el$('div').class$('bar').appendTo$(_.root);

        _.tabroot = el$('ul').appendTo$(bar);

        for ( var z in _.tabs ) {
            void _.add$(_.tabs[z], _.tabroot);
        }

        var ln = el$('div').appendTo$(bar).class$('line');

        if ( _.active==null && z ) {
            _.active = _.tabroot.firstChild.firstChild ? _.tabroot.firstChild.firstChild : _.tabroot.firstChild;
        }

    return _;
    };

}